package com.lingjtx.common.security.strategy;

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.lingjtx.common.core.RedisOptions;
import com.lingjtx.common.core.ResponseCode;
import com.lingjtx.common.core.ResponseResult;
import com.lingjtx.common.core.constant.RedisConfig;
import com.lingjtx.common.core.util.StringUtil;
import com.lingjtx.common.core.token.AuthToken;
import com.lingjtx.common.core.token.UserDetail;

/**
 * token有效&&redisToken==null ，说明用户重新登录过，被下线
 */
public class OfflineStrategy extends TokenStateHandler {

    private String info;

    public String getInfo() {
        return info;
    }

    public void setInfo(String info) {
        this.info = info;
    }

    @Override
    public ResponseResult<Object> retError() {
        return ResponseResult.createByError(ResponseCode.OFFLINE.getCode(), getInfo());
    }

    @Override
    public boolean handler(RedisOptions redis, String token) {
        if (StringUtil.isNotEmpty(token)) {
            UserDetail userDetail = AuthToken.getUser(token);
            if (userDetail != null && !redis.exists(token)) {
                if (userDetail.getOffline()) {
                    String hashKey = AuthToken.getRdsTokenHashKey(userDetail);
                    String lastToken = (String) redis.hmGet(RedisConfig.KEY_USER_TOKEN + userDetail.getUserId(), hashKey);
                    if (!token.equals(lastToken)) { // 传入的token与存储最后一次的token 不一致，说明被踢
                        String json = (String) redis.get(RedisConfig.KEY_LOGIN_LOG + userDetail.getUserId());
                        JSONObject map = JSON.parseObject(json);
                        if (map == null) {
                            this.setInfo(ResponseCode.OFFLINE.getDesc());
                            return false;
                        }
                        this.setInfo(String.format("你的账号 %s 在 %s 上已经登录了，如果不是本人操作请及时修改密码！登录地：%s",
                                map.get("createTime"),
                                map.get("deviceModel"),
                                map.get("address")));
                        return false;
                    }
                }
            }
        }
        return true;
    }
}
